package com.ynwa.rpc.simple;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @author gzd
 * @date 2017/12/25 17:09
 * @desc RPC 服务端的服务发布者
 */
public class RpcExporter {

    static Executor executor = Executors.newFixedThreadPool(Runtime.getRuntime()
            .availableProcessors());

    public static void exporter(String hostname, int port) throws Exception {
        ServerSocket server = new ServerSocket();
        server.bind(new InetSocketAddress(hostname, port));

        try {
            while (true) {
                executor.execute(new ExportTask(server.accept()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    private static class ExportTask implements Runnable {

        Socket client;

        public ExportTask(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {
            ObjectInputStream input = null;
            ObjectOutputStream outPut = null;

            try {
                input = new ObjectInputStream(client.getInputStream());
                String interfaceName = input.readUTF();

                Class<?> service = Class.forName(interfaceName);
                String methodName = input.readUTF();
                Class<?>[] parameterType = (Class<?>[]) input.readObject();

                Object[] args = (Object[]) input.readObject();
                Method method = service.getMethod(methodName, parameterType);
                Object result = method.invoke(service.newInstance(), args);

                outPut = new ObjectOutputStream(client.getOutputStream());

                outPut.writeObject(result);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if (outPut != null) {
                    try {
                        outPut.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if (client != null) {
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }


}
